namespace FsSignals
  module Signal = begin 
   
    /// Creates a function that returns a constant.
    val cst : 'a -> 'b -> 'a

    /// Compares object references
    val ( == ) : 'a -> 'b -> bool

    val private extract : ('a -> 'b option) -> 'a list -> 'b option * 'a list
    type InvalidSignal =
      {compute: World -> World;
       level: int;}
    and World  
      
    type Signal<'a> 

    /// Disposes a signal. 
    /// Notifies all dependent Signals
    /// De-registers from any Signals this Signal depends on.
    val dispose : Signal<'a> -> unit
 
    /// Creates a Signal that emit values a type 'a.
    /// The Signal can be triggered with the returned function
    val source : unit -> Signal<'a> * ('a -> unit)

    /// Creates a Signal from a IEvent.
    val sourceEvent :
      IEvent<'a,'a0> -> Signal<'a0>
        when 'a : delegate<'a0,unit> and 'a :> System.Delegate

    /// Create a Signal of type 'a but which never emit any value.
    val none : unit -> Signal<'a>

    /// Creates a Signal whose values are the result of applying the given function to values emitted by the input Signal.
    val map : ('a -> 'b) -> Signal<'a> -> Signal<'b>
    
    ///  Creates a Signal that listens to the input Signal and emits unchanged value when this value satisfies the given predicate.
    val filter : ('a -> bool) -> Signal<'a> -> Signal<'a>

    /// Returns a Signals that listens to the input Signal and emits value which is the result of the given mapping function.
    /// The result value is emitted only if the mapping function returns Some value.
    /// The new Signal does not emit a value when the mapping function returns None.
    val choose : ('a -> 'b option) -> Signal<'a> -> Signal<'b>

    val chooseSig : Signal<'a option> -> Signal<'a>

    /// Merges the two input Signals S1 and S2. Takes into account the fact that both Signal can simultaneous emit values. 
    /// If both Signals respectively emit values s1 and s2, the new Signal emits (Some s1, Some s2)
    /// If only S1 emits a value s1, the new Signal emits (Some s1, None)
    /// If only S2 emits a value s2, the new Signal emits (None, Some s2)
    /// If no input Signal emit a value, the new Signal does not emit a value.
    val merge : Signal<'a> -> Signal<'b> -> Signal<'a option * 'b option>

    /// Creates a Signal that does not emit any value until it has received, from its input Signal, a value for each element of the tuple ('a * 'b)
    /// Then this Signals forwards any modification of it value.
    val holdPair : Signal<'a option * 'b option> -> Signal<'a * 'b>

    /// Creates a Signal that applies the function carried by the first Signal to the value carried by the second.
    /// Wait until it has received a least one function and one value before emitting.
    val applySig : Signal<('a -> 'b)> -> Signal<'a> -> Signal<'b>

    val private innerSwitch :
      Signal<'a option * Signal<'a> option> -> Signal<'a>

    /// Creates a new Signal that is exactly the same as the first argument until it receives Signal value from the second argument.
    /// Then this new Signals becomes (swithes into) the Signal emitted by the second argument.
    val switch : Signal<'a> -> Signal<Signal<'a>> -> Signal<'a>
    
    /// Creates a new Signal that does not emit any value until it recieves a Signa value from the input Signal.
    /// Then this new Signals becomes (swithes into) the Signal emitted by the input Signal.
    val  wait : Signal<Signal<'a>> -> Signal<'a>

    /// Creates a Signal that applies the function carried by the first Signal to the value carried by the second.
    /// Wait until it has received a least one function and one value before emitting.
    /// This is the operator version of applySig.
    val ( <*> ) : Signal<('a -> 'b)> -> Signal<'a> -> Signal<'b>

    /// Creates a Signal whose values are the result of applying the given function to values emitted by the input Signal.
    /// This is the operator version of map.
    val ( =>> ) : Signal<'a> -> ('a -> 'b) -> Signal<'b>

    /// Creates a Signal that emits the given value whenever it receives a value from the input Signal.
    val ( --> ) : Signal<'a> -> 'b -> Signal<'b>

    /// Creates a Signal that emits the value returnd by the given function whenever it receives a value from the input Signal.
    val ( ==>> ) : Signal<'a> -> (unit -> 'b) -> Signal<'b>

    /// Merges two Signals. If both Signals simultaneously emits a value, the new Signal emits the value received by the first Signal.
    val mergeExc : Signal<'a> -> Signal<'a> -> Signal<'a>

    /// Creates a Signals whose values are the result of successively applying the function carried by the input Signal 
    /// to the previous value emitted by this new Signal.
    /// The first argument give the initial value to be passed to the function. 
    val stepAccumSig : 'a -> Signal<('a -> 'a)> -> Signal<'a>

    /// Creates a Signal that emits the last value received from the first input Signal whenever the second input Signal emits any value.
    val sample : Signal<'a> -> Signal<'b> -> Signal<'a>

    /// Creates a Signal that emits a unit value whenever it receives true from the first input Signal.
    val whileSig : Signal<bool> -> Signal<unit>

    /// Creates a Signal that emits a unit value whenever it receives false to true transition from the first input Signal.
    val whenSig : Signal<bool> -> Signal<unit>

    /// Creates a Signal that emits elements of the given list whenever it received a value from the input Signal.
    /// When the list is empty, this new Signal stops emitting values.
    val iterSig : 'a list -> Signal<'b> -> Signal<'a>
    
    /// Bug
    val iterNotifySig : 'a list -> Signal<'b> -> Signal<'a> * Signal<bool>

    /// Creates a Signal that emits elements of the given list whenever it received a value from the input Signal.
    /// When the list is empty, it starts gain with the same list
    val loopSig : 'a list -> Signal<'b> -> Signal<'a>

    /// Creates a Signal that applies the given function to each value received by the input Signal, threading a accumulator through the computation.
    /// The new Signalm emits intermediate values of the accumulator.
    val scan :
      ('state -> 'a -> 'state) -> 'state -> Signal<'a> -> Signal<'state>


    type 'a Alias =
      | Alias of ('a -> unit) * (unit -> 'a)
      with
        member get : ('a -> unit)
        member set : (unit -> 'a)
      end
    val aliasSig : unit -> unit Alias
    val bindSig : unit Alias -> Signal<unit> -> Signal<unit>
    val ( <.> ) : ('a -> 'b) -> Signal<'a> -> Signal<'b>
    val integrateSig :
      float -> float -> Signal<float> -> Signal<float> -> Signal<float>

    /// Creates a Signal that forward the first value emitted by the first input Signal.
    /// Then apply the given function to that value and switches into the resulting Signal.
    val onceThen: Signal<'a> -> ('a -> Signal<'a>) -> Signal<'a>

    /// The operator version of mergeExc
    val  (.||.) : Signal<'a> -> Signal<'a> -> Signal<'a>
    val print : Signal<'a> -> Signal<'a>

    /// Creates a Signal that emit a pair formed by  the values emitted by the two input Signals.
    /// This new Signal emit its first value once it has received at least one value from both input Signals.
    val two : Signal<'a> -> Signal<'b> -> Signal<'a * 'b>

    /// Creates a Signal that emit a triple formed by the values emitted by the three input Signals.
    /// This new Signal emit its first value once it has received at least one value from all input Signals.
    val three : Signal<'a> -> Signal<'b> -> Signal<'c> -> Signal<'a * 'b * 'c>
  end

